package com.miet.mp45.filippov.cryptoapplet.actionpanels;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JTextField;

import org.apache.log4j.Logger;

import com.miet.mp45.filippov.crypto.util.CryptoUtil;
import com.miet.mp45.filippov.cryptoapplet.actionpanels.events.ProcessingFinishedEventListener;
import com.miet.mp45.filippov.cryptoapplet.actionpanels.events.ProcessingStartedEventListener;
import com.miet.mp45.filippov.utils.IOUtilities;

public class GenerateCSRPanel extends ActionPanel
{

    private static final long serialVersionUID = 9017174895958433947L;
    
    private Logger logger = Logger.getLogger(this.getClass());
    private JButton generateButton = new JButton("Generate");
    private JButton privateKeyPathBrowseButton = new JButton("...");
    private JTextField cnTextField = new JTextField();
    private JTextField ouTextField = new JTextField();
    private JTextField oTextField = new JTextField();
    private JTextField cTextField = new JTextField();
    private JTextField privateKeyPathTextField = new JTextField();
    
    
    public GenerateCSRPanel(ProcessingStartedEventListener pseListener,
                            ProcessingFinishedEventListener pfeListener)
    {
        addPSEListener(pseListener);
        addPFEListener(pfeListener);
        initComponents();
    }
    
    private void initComponents()
    {

        javax.swing.JLabel cnLabel = new javax.swing.JLabel();
        cnTextField = new javax.swing.JTextField();
        javax.swing.JLabel keyPairPathLabel = new javax.swing.JLabel();
        privateKeyPathTextField = new javax.swing.JTextField();
        privateKeyPathBrowseButton = new javax.swing.JButton();
        generateButton = new javax.swing.JButton();
        ouTextField = new javax.swing.JTextField();
        javax.swing.JLabel ouLabel = new javax.swing.JLabel();
        cTextField = new javax.swing.JTextField();
        javax.swing.JLabel cLabel = new javax.swing.JLabel();
        oTextField = new javax.swing.JTextField();
        javax.swing.JLabel oLabel = new javax.swing.JLabel();

        cnLabel.setText("CN");

        keyPairPathLabel.setText("Keypair path:");

        privateKeyPathBrowseButton.setText("...");
        privateKeyPathBrowseButton.addActionListener(new java.awt.event.ActionListener()
        {
            public void actionPerformed(java.awt.event.ActionEvent evt)
            {
                keyPairPathBrowseButtonActionPerformed(evt);
            }
        });

        generateButton.setText("Generate");
        generateButton.addActionListener(new java.awt.event.ActionListener()
        {
            public void actionPerformed(java.awt.event.ActionEvent evt)
            {
                generateButtonActionPerformed(evt);
            }
        });

        ouLabel.setText("OU");

        cLabel.setText("C");

        oLabel.setText("O");

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(keyPairPathLabel)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(privateKeyPathTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 224, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(privateKeyPathBrowseButton))
                    .addComponent(generateButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addGroup(layout.createSequentialGroup()
                                .addComponent(cnLabel)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(cnTextField))
                            .addGroup(layout.createSequentialGroup()
                                .addComponent(ouLabel)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(ouTextField)))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 10, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                            .addGroup(layout.createSequentialGroup()
                                .addComponent(oLabel)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(oTextField))
                            .addGroup(layout.createSequentialGroup()
                                .addComponent(cLabel)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(cTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 122, javax.swing.GroupLayout.PREFERRED_SIZE)))))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(cnLabel)
                    .addComponent(cnTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(cLabel)
                    .addComponent(cTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(ouLabel)
                    .addComponent(ouTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(oLabel)
                    .addComponent(oTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addGap(18, 18, 18)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(keyPairPathLabel)
                    .addComponent(privateKeyPathTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(privateKeyPathBrowseButton))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(generateButton)
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
    }

    private void keyPairPathBrowseButtonActionPerformed(java.awt.event.ActionEvent evt)
    {
        FILE_CHOOSER.setFileFilter(PRIVATE_KEY_FILE_FILTER);
        if (FILE_CHOOSER.showOpenDialog(this) == JFileChooser.APPROVE_OPTION)
        {
            privateKeyPathTextField.setText(FILE_CHOOSER.getSelectedFile().getAbsolutePath());
        }
    }

    private void generateButtonActionPerformed(java.awt.event.ActionEvent evt)
    {
        if (isSomeFieldEmpty())
        {
            return;
        }
        
        FILE_CHOOSER.setFileFilter(CSR_FILE_FILTER);
        if (FILE_CHOOSER.showSaveDialog(this) == JFileChooser.APPROVE_OPTION)
        {
            new CryptoTask()
            {
                @Override
                public void doRun()
                {
                    String privateKeyPath = privateKeyPathTextField.getText();

                    FileOutputStream fos = null;
                    try
                    {
                        File file = FILE_CHOOSER.getSelectedFile();
                        logger.info("Generating CSR ...");
                        byte[] csr = CryptoUtil.generateCSR(cnTextField.getText(),
                                                              ouTextField.getText(),
                                                              oTextField.getText(),
                                                              cTextField.getText(),
                                                              IOUtilities.readFile(privateKeyPath));
                        logger.info("Writing csr into '" + file + "'");
                        fos = new FileOutputStream(file);
                        fos.write(csr);
                    }
                    catch (Exception ex)
                    {
                        logger.error(ex);
                    }
                    finally
                    {
                        if (fos != null)
                        {
                            try { fos.close(); } catch (IOException ex) { logger.error(ex); }
                        }
                    }
                }
            }.start();
        }
    }
    
    private boolean isSomeFieldEmpty()
    {
        return (cnTextField.getText().isEmpty() || cTextField.getText().isEmpty() ||
                ouTextField.getText().isEmpty() || oTextField.getText().isEmpty() ||
                privateKeyPathTextField.getText().isEmpty());
    }

}
